module;
#include <type_traits>
#include <cstddef>

export module Code_19_8_2;

//[1]
template<typename T>
struct IsPointerT : std::false_type {}; //primary template: by defaultnot a pointer
//[1]
template<typename T>
struct IsPointerT<T*> : std::true_type //partial specializationforpointers
{ 
    using BaseT = T; // type pointing to
};

//[2]
template<typename T>
struct IsLValueReferenceT : std::false_type {}; //by default no lvaluereference
//[2]
template<typename T>
struct IsLValueReferenceT<T&> : std::true_type  //unless T is lvaluereferences
{ 
    using BaseT = T; // type referring to
};

//[3]
template<typename T>
struct IsRValueReferenceT : std::false_type {};  //by default no rvaluereference
//[3]
template<typename T>
struct IsRValueReferenceT<T&&> : std::true_type  //unless T is rvaluereference
{
    using BaseT = T; // type referring to
};



//[4]
template<bool COND, typename TrueType, typename FalseType>
struct IfThenElseT
{
    using Type = TrueType;
};
//[4]
template<typename TrueType, typename FalseType>
struct IfThenElseT<false, TrueType, FalseType>
{
    using Type = FalseType;
};
//[4]
template<bool COND, typename TrueType, typename FalseType>
using IfThenElse = typename IfThenElseT<COND, TrueType, FalseType>::Type;
//[4]
template<typename T>
class IsReferenceT  : public IfThenElseT<
                                        IsLValueReferenceT<T>::value,
                                        IsLValueReferenceT<T>,
                                        IsRValueReferenceT<T>
                                        >::Type 
{
};

//[5]
template<typename T>
struct IsArrayT : std::false_type {}; //primary template: not an array
//[5]
template<typename T, std::size_t N>
struct IsArrayT<T[N]> : std::true_type //partial specializationforarrays 
{ 
    using BaseT = T;
    static constexpr std::size_t size = N;
};
//[5]
template<typename T>
struct IsArrayT<T[]> : std::true_type //partial specializationforunbound arrays
{ 
    using BaseT = T;
    static constexpr std::size_t size = 0;
};


//[6]
template<typename T>
struct IsPointerToMemberT : std::false_type {}; //by default no pointer-to-member
//[6]
template<typename T, typename C>
struct IsPointerToMemberT<T C::*> : std::true_type  //partial specialization
{
    using MemberT = T;
    using ClassT = C;
};


export
namespace Code_19_8_2 {

    void run()
    {

    }
}
